﻿using Lightworks.Core.Cache;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Lightworks.Core.Auth
{
    public class JwtService
    {
        ICacheService cache;
        JwtConfig? config;
        public JwtService(ICacheService cache, JwtConfig? config) 
        {
            this.cache = cache;
            this.config = config;
        }

        public string GenerateAccessToken(string uId)
        {
            var claims = new[]
            {
                new Claim(ClaimTypes.Name, uId)
            };
            var secretByte = Encoding.UTF8.GetBytes(config.SecretKey!);
            var signKey = new SymmetricSecurityKey(secretByte);
            var credential = new SigningCredentials(signKey, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
                issuer: config.ValidIssuer,
                audience: config.ValidAudience,
                claims,
                notBefore: DateTime.UtcNow,
                expires: DateTime.UtcNow.AddMinutes(config.ExpireTime),
                credential
            ) ;

            var handler = new JwtSecurityTokenHandler();
            var tokenStr = handler.WriteToken(token);

            return tokenStr;
        }

        public bool Validate(string token)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(config.SecretKey);
            try
            {
                tokenHandler.ValidateToken(token, new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = config.ValidIssuer,
                    ValidAudience = config.ValidAudience,
                    IssuerSigningKey = new SymmetricSecurityKey(key)
                }, out var validatedToken);
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        public string GenerateRefreshToken(string uId)
        {
            var randomNumber = RandomNumberGenerator.GetBytes(32);
            var ret = Convert.ToBase64String(randomNumber);
            //缓存刷新令牌
            cache.Add($"system:user:login:refreshtoken:{uId}", ret);
            return ret;
        }

        public string Refresh(string accessToken, string refreshToken, string uId)
        {
            //通过缓存后去令牌比对,
            var cachetoken = cache.Get($"system:user:login:refreshtoken:{uId}");
            if (cachetoken == null || cachetoken != refreshToken)
            {
                throw new Exception("无效的刷新令牌，非法访问");
            }
            var handler = new JwtSecurityTokenHandler();
            var token = handler.ReadJwtToken(accessToken);
            if (token.ValidTo > DateTime.UtcNow.AddMinutes(3)) // 三分鐘內有效直接返回 
            {
                return accessToken;
            }
            var uid = token.Claims.First(x => x.Type == ClaimTypes.Name).Value;
            return GenerateAccessToken(uid);
        }
    }
}
